# Button

## Import

```js
import { Button } from 'bumbag';
```

## Usage

### Basic usage

```jsx-live
<Button>Default</Button>
```

### Colors

Colors can be added to a button with the `palette` prop.

```jsx-live
<Set>
  <Button>Default</Button>
  <Button palette="gray">Gray</Button>
  <Button palette="primary">Primary</Button>
  <Button palette="secondary">Secondary</Button>
  <Button palette="success">Success</Button>
  <Button palette="danger">Danger</Button>
  <Button palette="warning">Warning</Button>
</Set>
```

### Variants

```jsx-live
<Set>
  <Button palette="primary">Default</Button>
  <Button variant="outlined" palette="primary">Outlined</Button>
  <Button variant="ghost" palette="primary">Ghost</Button>
  <Button variant="link" palette="primary">Link</Button>
</Set>
```

### Icons

You can add icons to your buttons with the `iconBefore` or `iconAfter` prop.

**Note:** To use button icons, you will need to follow the [instructions to set up icons with Bumbag](/components/icon).

```jsx-live
<Set>
  <Button iconBefore="solid-clipboard">Copy</Button>
  <Button iconBefore="solid-pen" palette="primary">
    Edit
  </Button>
  <Button iconAfter="solid-long-arrow-alt-right">Continue</Button>
  <Button iconBefore="info-circle" iconBeforeProps={{ fontSize: '300' }}>Info</Button>
</Set>
```

### Loading

To indicate a button is loading, use the `isLoading` prop.

```jsx-live
<Set>
  <Button isLoading>Hello world</Button>
  <Button isLoading palette="primary">Hello world</Button>
</Set>
```

### Outlines

An outline can be placed on a button by assigning `"outlined"` to the `variant` prop.

```jsx-live
<Set>
  <Button palette="primary" variant="outlined">
    Primary
  </Button>
  <Button palette="secondary" variant="outlined">
    Secondary
  </Button>
  <Button palette="success" variant="outlined">
    Success
  </Button>
  <Button palette="danger" variant="outlined">
    Danger
  </Button>
</Set>
```

### Ghost

To have a button of minimal appearence, use the assign `"ghost"` to the `variant` prop.

```jsx-live
<Set>
  <Button variant="ghost">Default</Button>
  <Button palette="primary" variant="ghost">
    Primary
  </Button>
  <Button palette="success" variant="ghost">
    Success
  </Button>
  <Button palette="danger" variant="ghost">
    Danger
  </Button>
  <Button palette="warning" variant="ghost">
    Warning
  </Button>
</Set>
```

### Sizes

Buttons are available in four different sizes and can be added with a `size` prop.

```jsx-live
<Set>
  <Button size="small">Small</Button>
  <Button>Default</Button>
  <Button size="medium">Medium</Button>
  <Button size="large">Large</Button>
</Set>
```

### Links

A button can appear as a link with no styling by assigning `"link"` to the `type` prop.

```jsx-live
<Button palette="primary" variant="link">
  Default
</Button>
```

### Static

To make a button non-interactable, add the `isStatic` prop.

```jsx-live
<Button isStatic>Static</Button>
```

### Disabled

To indicate a button as disabled, use the `disabled` prop.

```jsx-live
<Set>
  <Button disabled>Default</Button>
  <Button palette="primary" disabled>
    Primary
  </Button>
  <Button palette="success" disabled>
    Success
  </Button>
  <Button palette="danger" disabled>
    Danger
  </Button>
  <Button palette="warning" disabled>
    Warning
  </Button>
</Set>
```

### Sets

To display a set of buttons, use the [`<Set>` component](/components/set).

```jsx-live
<Set>
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</Set>
```

### Group

To group a set of buttons together, use the `<Group>` component.

```jsx-live
<Group>
  <Button>Button 1</Button>
  <Button>Button 2</Button>
  <Button>Button 3</Button>
</Group>
```

### Close Buttons

```jsx-live
<Set>
  <Button.Close size="small" />
  <Button.Close />
  <Button.Close size="large" />
</Set>
```

## Composition

### `use`

Button, by default, renders a `<button>` element.
However, you are able to change it to a custom element using the `use` prop.

```jsx-live
<Set>
  <Button>Default</Button>
  <Button use="a" href="#">
    Anchor
  </Button>
</Set>
```

### `Button.useProps()` Hook

The world is your oyster! You can use the `Button.useProps()` hook to spread button props wherever!

```function-live
function Example() {
  const buttonProps = Button.useProps();
  return (
    <a {...buttonProps}>Hello world</a>
  )
}
```

### Render props

```jsx-live
<Button>
  {buttonProps => <a {...buttonProps}>Hello world</a>}
</Button>
```

## Accessibility

The `<Button>` component follows the [WAI ARIA Button Pattern](https://www.w3.org/TR/wai-aria-practices/#button).

### Rules

- `Button` has an accessible label denoted by it's content. If your button has no content, `ariaLabel` or `ariaLabelledby` can be used to label the button.
- If a description of `Button`'s' function is present, the `ariaDescribedby` prop can be set to the `id` of the component containing the description.

#### Patterns

- `Button` has a role of `button`.
- When a `Button` has focus, <Key>Space</Key> or <Key>Enter</Key> activates it.
- When a `Button` is disabled, the `disabled` and `aria-disabled` attributes are set to `true`.
- If a `Button` is composed of another element (such as `div` or `a`), accessible button attributes are set on the element.

#### References

- [WAI ARIA Button Pattern](https://www.w3.org/TR/wai-aria-practices/#button)

## Props

### Button Props

<!-- Automatically generated -->

**<Code fontSize="150" marginRight="major-1">iconAfter</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | IconDefinition
  | { viewBoxHeight: number; viewBoxWidth: number; paths?: string[]; tree?: any[]; }`}
</Code>

Icon that appears on the right side of the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconAfterProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  unstable_system?: any;
  top?: any;
  right?: any;
  bottom?: any;
  left?: any;
  children?: string | number | boolean | {
     | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 47 more ... | (ReactPortal...`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconBefore</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | IconDefinition
  | { viewBoxHeight: number; viewBoxWidth: number; paths?: string[]; tree?: any[]; }`}
</Code>

Icon that appears on the left side of the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconBeforeProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  unstable_system?: any;
  top?: any;
  right?: any;
  bottom?: any;
  left?: any;
  children?: string | number | boolean | {
     | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 47 more ... | (ReactPortal...`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">isLoading</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Adds a loading indicator to the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">isStatic</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Makes the button not interactable.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">palette</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`"default"
  | "primary"
  | "secondary"
  | "success"
  | "danger"
  | "warning"
  | (string & {})`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">size</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`"default"
  | (string & {})
  | "small"
  | "medium"
  | "large"`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">spinnerProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`BoxOptions & HTMLAttributes<any> & RefAttributes<any> & { wrapElement?: (element: ReactNode) => ReactNode; } & CSSProperties & LocalBoxProps & LocalSpinnerProps`}
</Code>

Custom props for the isLoading spinner.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">type</Code>** <Code fontSize="100" palette="primary">&#34;submit&#34; | &#34;reset&#34; | &#34;button&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">ignoreGrayOverride</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">disabled</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Same as the HTML attribute.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">focusable</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

When an element is `disabled`, it may still be `focusable`. It works
similarly to `readOnly` on form elements. In this case, only
`aria-disabled` will be set.

<Divider marginTop="major-2" marginBottom="major-2" />

<details><Box use="summary" marginBottom="major-2">Inherits <strong><code>Box</code></strong> props</Box>

**<Code fontSize="150" marginRight="major-1">use</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">className</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">children</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignX</Code>** <Code fontSize="100" palette="primary">&#34;right&#34; | &#34;left&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignY</Code>** <Code fontSize="100" palette="primary">&#34;top&#34; | &#34;bottom&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">variant</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">colorMode</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">overrides</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 96 more ...;
  Template?: TemplateThemeConfig;
}`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">elementRef</Code>** <Code fontSize="100" palette="primary">((instance: any) =&#62; void) | RefObject&#60;any&#62;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">themeKey</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

</details>
            

### Button.Close Props

<!-- Automatically generated -->

**<Code fontSize="150" marginRight="major-1">iconProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  unstable_system?: any;
  top?: any;
  right?: any;
  bottom?: any;
  left?: any;
  children?: string | number | boolean | {
     | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 47 more ... | (ReactPortal...`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">label</Code>** <Code fontSize="100" palette="primary">string</Code> 

Accessible label for the button. Default: `"Close"`

<Divider marginTop="major-2" marginBottom="major-2" />

<details><Box use="summary" marginBottom="major-2">Inherits <strong><code>Button</code></strong> props</Box>

**<Code fontSize="150" marginRight="major-1">iconAfter</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | IconDefinition
  | { viewBoxHeight: number; viewBoxWidth: number; paths?: string[]; tree?: any[]; }`}
</Code>

Icon that appears on the right side of the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconAfterProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  unstable_system?: any;
  top?: any;
  right?: any;
  bottom?: any;
  left?: any;
  children?: string | number | boolean | {
     | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 47 more ... | (ReactPortal...`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconBefore</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | IconDefinition
  | { viewBoxHeight: number; viewBoxWidth: number; paths?: string[]; tree?: any[]; }`}
</Code>

Icon that appears on the left side of the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">iconBeforeProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  unstable_system?: any;
  top?: any;
  right?: any;
  bottom?: any;
  left?: any;
  children?: string | number | boolean | {
     | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)>) | (new (props: any) => Component<...>)> | ... 47 more ... | (ReactPortal...`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">isLoading</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Adds a loading indicator to the button.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">isStatic</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Makes the button not interactable.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">palette</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`"default"
  | "primary"
  | "secondary"
  | "success"
  | "danger"
  | "warning"
  | (string & {})`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">size</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`"default"
  | (string & {})
  | "small"
  | "medium"
  | "large"`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">spinnerProps</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`BoxOptions & HTMLAttributes<any> & RefAttributes<any> & { wrapElement?: (element: ReactNode) => ReactNode; } & CSSProperties & LocalBoxProps & LocalSpinnerProps`}
</Code>

Custom props for the isLoading spinner.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">type</Code>** <Code fontSize="100" palette="primary">&#34;submit&#34; | &#34;reset&#34; | &#34;button&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">ignoreGrayOverride</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">disabled</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

Same as the HTML attribute.

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">focusable</Code>** <Code fontSize="100" palette="primary">boolean</Code> 

When an element is `disabled`, it may still be `focusable`. It works
similarly to `readOnly` on form elements. In this case, only
`aria-disabled` will be set.

<Divider marginTop="major-2" marginBottom="major-2" />

</details>
            

<details><Box use="summary" marginBottom="major-2">Inherits <strong><code>Box</code></strong> props</Box>

**<Code fontSize="150" marginRight="major-1">use</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | (ComponentClass<any, any> & { useProps: any; })
  | (FunctionComponent<any> & { useProps: any; })`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">className</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">children</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`string
  | number
  | boolean
  | {}
  | ReactElement<any, string
  | ((props: any) => ReactElement<any, string
  | ...
  | (new (props: any) => Component<any, any, any>)>)
  | (new (props: any) => Component<...>)>
  | ReactNodeArray
  | ReactPortal
  | ((props: BoxProps) => ReactNode)`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignX</Code>** <Code fontSize="100" palette="primary">&#34;right&#34; | &#34;left&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">alignY</Code>** <Code fontSize="100" palette="primary">&#34;top&#34; | &#34;bottom&#34; | &#34;center&#34;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">variant</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">colorMode</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">overrides</Code>**  

<Code isBlock palette="primary" fontSize="150" padding="minor-1" marginBottom="major-2">
{`{
  useCSSVariables?: boolean;
  altitudes?: AltitudesThemeConfig;
  borders?: BordersThemeConfig;
  borderRadii?: BorderRadiiThemeConfig;
  ... 96 more ...;
  Template?: TemplateThemeConfig;
}`}
</Code>

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">elementRef</Code>** <Code fontSize="100" palette="primary">((instance: any) =&#62; void) | RefObject&#60;any&#62;</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

**<Code fontSize="150" marginRight="major-1">themeKey</Code>** <Code fontSize="100" palette="primary">string</Code> 

<Divider marginTop="major-2" marginBottom="major-2" />

</details>
            

## Theming

<Theme
  component={'Button'}
  overrides={[
    'Button.styles.base',
    {
      key: 'Button.styles.disabled',
      description: 'Applies when the button is disabled. `<Button disabled>`',
      props: { disabled: true }
    },
    { key: 'Button.styles.focus', description: 'Applies when the button has focus. Try it out by clicking the button.' },
    { key: 'Button.styles.hover', description: 'Applies when the button is hovered. Try it out by hovering over the button.' },
    {
      key: 'Button.styles.hoveractive',
      description:
        'Applies when the button is hovered and active. Try it out by hovering over the button and clicking on it.'
    },
    {
      key: 'Button.styles.ghost',
      description: 'Applies for ghost buttons. `<Button variant="ghost">`',
      props: { variant: 'ghost' }
    },
    { key: 'Button.styles.link', description: 'Applies for link buttons. `<Button variant="link">`', props: { variant: 'link' } },
    {
      key: 'Button.styles.outlined',
      description: 'Applies for outlined buttons. `<Button variant="outlined">`',
      props: { variant: 'outlined' }
    },
    { key: 'Button.styles.static', description: 'Applies for static buttons. `<Button isStatic>`', props: { isStatic: true } },
    {
      key: 'Button.styles.sizes.small',
      description: 'Applies for small buttons. `<Button size="small">`',
      props: [{ size: 'small' }, { size: 'default' }, { size: 'medium' }, { size: 'large' }]
    },
    {
      key: 'Button.styles.sizes.default',
      props: [{ size: 'small' }, { size: 'default' }, { size: 'medium' }, { size: 'large' }]
    },
    {
      key: 'Button.styles.sizes.medium',
      description: 'Applies for static buttons. `<Button size="medium">`',
      props: [{ size: 'small' }, { size: 'default' }, { size: 'medium' }, { size: 'large' }]
    },
    {
      key: 'Button.styles.sizes.large',
      description: 'Applies for static buttons. `<Button size="large">`',
      props: [{ size: 'small' }, { size: 'default' }, { size: 'medium' }, { size: 'large' }]
    },
    {
      key: 'Button.Icon.styles.base',
      props: { iconBefore: 'info-circle' }
    },
    {
      key: 'Button.Icon.styles.before',
      props: { iconBefore: 'info-circle' }
    },
    {
      key: 'Button.Icon.styles.after',
      props: { iconAfter: 'info-circle' }
    }
  ]}>
  Hello world
</Theme>
